package ru.reaperoq.inventory.screens.main.admin.objects

import LoadingStatus
import admin.models.CreateComponent
import admin.models.CreateComputer
import android.util.Log
import android.widget.Toast
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.QrCodeScanner
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import edit.EditObjectViewModel
import edit.models.EditObjectsEvent
import models.LocationUi
import models.shared.UserUi
import my.models.ComputerUi
import ru.reaperoq.inventory.components.button.BigButton
import ru.reaperoq.inventory.components.textField.DateTextField
import ru.reaperoq.inventory.components.textField.DropDownTextField

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun EditObjectsScreen(
    modifier: Modifier = Modifier,
    id: Int? = null,
    key: String,
    userRole: UserUi.Role,
    viewModel: EditObjectViewModel,
    onOpenScanner: (String) -> Unit,
    onBack: () -> Unit
) {
    Log.d("KEY", key)
    val viewState by viewModel.viewStates().collectAsState()

    val isSent by remember(viewState.loadingStatus) { mutableStateOf(viewState.loadingStatus == LoadingStatus.FullyLoad) }

    LaunchedEffect(isSent) {
        if (isSent) {
            onBack()
        }
    }

    LaunchedEffect(id) {
        if (id != null) {
            viewModel.obtainEvent(EditObjectsEvent.SetId(id))
        }
    }

    Scaffold(
        modifier = Modifier
            .statusBarsPadding()
            .imePadding(),
        topBar = {
            val text = if (id == null) "Добавить" else "Изменить"
            CenterAlignedTopAppBar(
                title = { Text(text) },
                navigationIcon = {
                    IconButton(onClick = onBack) {
                        Icon(
                            imageVector = Icons.AutoMirrored.Default.ArrowBack,
                            contentDescription = null
                        )
                    }
                }
            )
        }
    ) { padding ->
        Column(
            modifier = modifier
                .consumeWindowInsets(padding)
                .padding(padding)
                .verticalScroll(rememberScrollState()),
            verticalArrangement = Arrangement.SpaceAround,
            horizontalAlignment = Alignment.Start
        ) {
            if (id != null && viewState.obj == null) {
                Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                    CircularProgressIndicator()
                }
            } else {
                if (viewState.loadingStatus is LoadingStatus.Loading) {
                    LinearProgressIndicator(Modifier.fillMaxWidth())
                }
                if (id == null) {
                    Row(
                        modifier = Modifier.fillMaxWidth(),
                        verticalAlignment = Alignment.CenterVertically,
                        horizontalArrangement = Arrangement.spacedBy(8.dp)
                    ) {
                        Row(
                            verticalAlignment = Alignment.CenterVertically,
                            horizontalArrangement = Arrangement.spacedBy(8.dp)
                        ) {
                            RadioButton(
                                selected = viewState.obj is CreateComputer,
                                onClick = {
                                    viewModel.obtainEvent(EditObjectsEvent.SetObject(CreateComputer()))
                                }
                            )
                            Text(text = "Компьютер")
                        }
                        Row(
                            verticalAlignment = Alignment.CenterVertically,
                            horizontalArrangement = Arrangement.spacedBy(8.dp)
                        ) {
                            RadioButton(
                                selected = viewState.obj is CreateComponent,
                                onClick = {
                                    viewModel.obtainEvent(EditObjectsEvent.SetObject(CreateComponent()))
                                }
                            )
                            Text(text = "Компонент")
                        }
                    }
                }
                when (val obj = viewState.obj) {
                    is CreateComputer -> EditComputerContent(
                        userRole = userRole,
                        id = id,
                        computer = obj,
                        locations = viewState.locations,
                        isLoading = viewState.loadingStatus is LoadingStatus.Loading,
                        onOpenScanner = {
                            onOpenScanner(key)
                        }
                    ) { computer ->
                        viewModel.obtainEvent(EditObjectsEvent.SetObject(computer))
                        viewModel.obtainEvent(EditObjectsEvent.SendObject)
                    }

                    is CreateComponent -> EditComponentContent(
                        userRole = userRole,
                        id = id,
                        component = obj,
                        locations = viewState.locations,
                        computers = viewState.computers,
                        types = viewState.componentTypes,
                        isLoading = viewState.loadingStatus is LoadingStatus.Loading,
                        onOpenScanner = {
                            onOpenScanner(key)
                        }
                    ) { component ->
                        viewModel.obtainEvent(EditObjectsEvent.SetObject(component))
                        viewModel.obtainEvent(EditObjectsEvent.SendObject)
                    }

                    null -> {
                        Text("Выберите объект", modifier = Modifier.padding(8.dp))
                    }
                }
            }
        }
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun EditComputerContent(
    modifier: Modifier = Modifier,
    userRole: UserUi.Role,
    id: Int? = null,
    computer: CreateComputer,
    locations: List<LocationUi>,
    isLoading: Boolean,
    onOpenScanner: () -> Unit,
    onSave: (CreateComputer) -> Unit,
) {
    val showSerial = remember { id == null }
    var serial by remember { mutableStateOf(computer.serialNumber) }
    var model by remember { mutableStateOf(computer.model) }
    var manufacturer by remember { mutableStateOf(computer.manufacturer) }
    var purchaseDate by remember { mutableLongStateOf(computer.purchaseDate) }
    var locationName by remember { mutableStateOf(computer.locationName) }
    val locationId by remember(locationName) {
        mutableIntStateOf(
            if (computer.locationId != -1) computer.locationId
            else locations.firstOrNull { it.name == locationName }?.id ?: -1
        )
    }
    var notes by remember { mutableStateOf(computer.notes) }

    val context = LocalContext.current

    Column(
        modifier = modifier
            .padding(horizontal = 8.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        OutlinedTextField(
            modifier = modifier.fillMaxWidth(),
            value = serial,
            onValueChange = { serial = it },
            label = { Text("Инв. номер") },
            enabled = showSerial,
            trailingIcon = {
                IconButton(onClick = onOpenScanner, enabled = showSerial) {
                    Icon(imageVector = Icons.Default.QrCodeScanner, contentDescription = null)
                }
            }
        )
        OutlinedTextField(
            modifier = modifier.fillMaxWidth(),
            value = model,
            onValueChange = { model = it },
            label = { Text("Модель") }
        )
        OutlinedTextField(
            modifier = modifier.fillMaxWidth(),
            value = manufacturer,
            onValueChange = { manufacturer = it },
            label = { Text("Производитель") }
        )
        DateTextField(
            label = "Дата покупки",
            startDate = purchaseDate,
            onChange = { purchaseDate = it }
        )
        DropDownTextField(
            data = locations.map { it.name },
            value = locationName,
            labelText = "Местоположение",
            readOnly = userRole != UserUi.Role.ADMIN
        ) {
            locationName = it
        }
        OutlinedTextField(
            modifier = modifier.fillMaxWidth(),
            value = notes ?: "",
            onValueChange = { notes = it },
            label = { Text("Примечания") }
        )

        BigButton(
            Modifier
                .padding(bottom = 16.dp)
                .align(Alignment.CenterHorizontally)
                .height(60.dp),
            onClick = {
                if (
                    serial.isNotBlank() &&
                    model.isNotBlank() &&
                    manufacturer.isNotBlank() &&
                    purchaseDate != 0L &&
                    locationName.isNotBlank()
                ) {
                    onSave(
                        CreateComputer(
                            serialNumber = serial,
                            model = model,
                            manufacturer = manufacturer,
                            purchaseDate = purchaseDate,
                            locationName = locationName,
                            locationId = locationId,
                            notes = notes
                        )
                    )
                } else {
                    Toast.makeText(context, "Заполните все поля", Toast.LENGTH_SHORT).show()
                }
            },
            enabled = !isLoading
        ) {
            Text(text = "Сохранить")
        }
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun EditComponentContent(
    modifier: Modifier = Modifier,
    userRole: UserUi.Role,
    id: Int? = null,
    component: CreateComponent,
    locations: List<LocationUi>,
    computers: List<ComputerUi>,
    types: List<String>,
    isLoading: Boolean,
    onOpenScanner: () -> Unit,
    onSave: (CreateComponent) -> Unit
) {
    val context = LocalContext.current

    val showSerial = remember { id == null }
    var name by remember { mutableStateOf(component.name) }
    var serialNumber by remember { mutableStateOf(component.serialNumber) }
    var type by remember { mutableStateOf(component.type) }
    var specifications by remember { mutableStateOf(component.specifications) }
    var purchaseDate by remember { mutableLongStateOf(component.purchaseDate) }
    var locationName by remember { mutableStateOf(component.locationName) }
    val locationId by remember(locationName) {
        mutableIntStateOf(
            if (component.locationId != -1) component.locationId
            else locations.firstOrNull { it.name == locationName }?.id ?: -1
        )
    }
    var computerName by remember {
        mutableStateOf(
            computers.firstOrNull { it.id == component.computerId }?.let {
                "${it.manufacturer} ${it.model}"
            } ?: ""
        )
    }
    val computerId by remember(computerName) {
        mutableStateOf(
            computers.firstOrNull { it.manufacturer + " " + it.model == computerName }?.id
        )
    }

    Column(
        modifier = modifier
            .padding(horizontal = 8.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        OutlinedTextField(
            modifier = modifier.fillMaxWidth(),
            value = serialNumber,
            onValueChange = { serialNumber = it },
            enabled = showSerial,
            label = { Text("Инв. номер") },
            trailingIcon = {
                IconButton(onClick = onOpenScanner, enabled = showSerial) {
                    Icon(imageVector = Icons.Default.QrCodeScanner, contentDescription = null)
                }
            }
        )
        DropDownTextField(data = types, value = type, labelText = "Тип") {
            type = it
        }
        OutlinedTextField(
            modifier = modifier.fillMaxWidth(),
            value = name,
            onValueChange = { name = it },
            label = { Text("Название") }
        )
        DateTextField(
            startDate = purchaseDate,
            label = "Дата покупки",
            onChange = {
                Log.d("VIEWMODEL", it.toString())
                purchaseDate = it
            }
        )
        DropDownTextField(
            data = locations.map { it.name },
            value = locationName,
            labelText = "Местоположение",
            readOnly = userRole != UserUi.Role.ADMIN
        ) {
            locationName = it
        }
        DropDownTextField(
            data = computers.map { "${it.manufacturer} ${it.model}" },
            value = computerName,
            labelText = "Компьютер",
            readOnly = true
        ) {
            computerName = it
        }
        OutlinedTextField(
            modifier = modifier.fillMaxWidth(),
            value = specifications,
            onValueChange = { specifications = it },
            label = { Text("Характеристики") }
        )
        BigButton(
            Modifier
                .padding(bottom = 16.dp)
                .align(Alignment.CenterHorizontally)
                .height(60.dp),
            onClick = {
                if (
                    serialNumber.isNotBlank() &&
                    type.isNotBlank() &&
                    name.isNotBlank() &&
                    purchaseDate != 0L &&
                    locationName.isNotBlank()
                ) {
                    onSave(
                        CreateComponent(
                            name = name,
                            serialNumber = serialNumber,
                            locationName = locationName,
                            locationId = locationId,
                            type = type,
                            specifications = specifications,
                            computerId = computerId,
                            purchaseDate = purchaseDate
                        )
                    )
                } else {
                    Toast.makeText(context, "Заполните все поля", Toast.LENGTH_SHORT).show()
                }
            },
            enabled = !isLoading
        ) {
            Text(text = "Сохранить")
        }
    }
}